﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Threading;
using EzDesk.Core.Model;
using EzDesk.DesktopClient.ServiceLocator.CoreClientService;
using EzDesk.Generic;
using EzDesk.DesktopClient.Event;
using EzDesk.EventAggregation;

namespace EzDesk.DesktopClient
{
    /// <summary>
    /// @Refactory 
    /// This class should be split into 2 classes.
    /// </summary>
    public class UpdateDataManagement : ManagementBase<UpdateDataManagement>
    {
        private readonly DispatcherTimer _disappearTimer = new DispatcherTimer();
        public TimeSpan DurationTime = TimeSpan.FromSeconds(8);
        private bool _isRunning = false;
        private readonly object _lockObj = new object();
        private readonly Dictionary<string,FeedStatus> _feeds = new Dictionary<string, FeedStatus>();

        public UpdateDataManagement()
        {
            InitTickEvent();
            InitEvent();
        }

        public UpdateDataManagement(ICoreClientService coreClientService, IUserManagement userManagement)
            : this()
        {
            _coreClientService = coreClientService;
            _userManagement = userManagement;
        }

        public void Start(int duration)
        {
            DurationTime = TimeSpan.FromSeconds(duration);
            SetDuration();
            this.Start();
        }

        private void SetDuration()
        {
            _disappearTimer.Interval = DurationTime;
        }

        public void Start()
        {
            _disappearTimer.Start();
        }

        public void Stop()
        {
            _disappearTimer.Stop();
        }

        
        private void InitTickEvent()
        {
            _disappearTimer.Tick += (sender, e) =>
            {
                this.UpdateFeedStatusFromClientToServer();
            };
            SetDuration();
        }

        public void UpdateFeedStatusFromClientToServer()
        {
            if (_feeds.Count == 0) return;

            this.CoreClientService.UpdateFeedStatus(this._feeds.Values.ToArray(), CurrentUser.Id.ToString());

            lock (_lockObj)
            {
                _feeds.Clear();
            }
        }

        private void InitEvent()
        {
            LoginEvent.Instance.Subscribe(this.OnUserLogin, ThreadOption.PublisherThread);
            LogoutEvent.Instance.Subscribe(this.OnUserLogout, ThreadOption.BackgroundThread);
            FeedStatusChangeEvent.Instance.Subscribe(this.UpdateFeedStatusInCache, ThreadOption.PublisherThread);
        }

        private void OnUserLogin(LoginArgs args)
        {
            args.IsSuccess.TrueDo(this.Start);
        }

        private void OnUserLogout(LogoutArgs args)
        {
            this.Stop();
        }

        public void UpdateFeedStatusInCache(Model.Feed feedModel)
        {
            CheckIfContainThisModel(feedModel.FeedID);

            this._feeds[feedModel.FeedID].FeedId = new Guid(feedModel.FeedID);
            this._feeds[feedModel.FeedID].IsRead = feedModel.IsRead;
            this._feeds[feedModel.FeedID].IsAvailable = feedModel.IsAvailable;
            this._feeds[feedModel.FeedID].IsMark = feedModel.IsMark;
        }

        private void CheckIfContainThisModel(string feedId)
        {
            lock (_lockObj)
            {
                if (!this._feeds.ContainsKey(feedId))
                    this._feeds.Add(feedId, new FeedStatus());
            }
        }
    }
}
